/**
 * Copyright 厦门中软海晟信息技术有限公司 版权所有 违者必究 2019
 */
package com.opencvjava.practise;

import org.opencv.core.Mat;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import static com.opencvjava.support.util.CvUtils.imshow;
import static com.opencvjava.support.util.CvUtils.mat;
import static org.opencv.imgcodecs.Imgcodecs.IMREAD_GRAYSCALE;

/**
 * @author : sunzb
 * @date: 2019/6/10
 */
@Service
public class Test1 {

    static class Pixel {
        int row;
        int col;
        int compareColor;

        public int getRow() {
            return row;
        }

        public Pixel setRow(int row) {
            this.row = row;
            return this;
        }

        public int getCol() {
            return col;
        }

        public Pixel setCol(int col) {
            this.col = col;
            return this;
        }

        public int getCompareColor() {
            return compareColor;
        }

        public Pixel setCompareColor(int compareColor) {
            this.compareColor = compareColor;
            return this;
        }
    }

    public void test() {
        Mat gray = mat("hand.jpg", IMREAD_GRAYSCALE);
        imshow("灰度图", gray);
        int rows = gray.rows();
        int cols = gray.cols();
        int total = (int) gray.total();
        byte[] bytes = new byte[total];
        gray.get(0, 0, bytes);
        int[] data = new int[total];
        for (int i = 0; i < total; i++) data[i] = bytes[i] & 0xff;
        long start = System.currentTimeMillis();
        List<List<Integer>> layers = new ArrayList<>();
        int color;
        for (int row = 0; row < rows; row++) for (int col = 0; col < cols; col++) {
            color = data[row * cols + col];
            if (color != -1) bfs(rows, cols, data, layers, new Pixel().setRow(row).setCol(col).setCompareColor(color));
        }
        int delta = 255 / (layers.size() + 1);
        color = 0;
        System.out.println(String.format("layer size:%s, cost:%sms, delta:%s", layers.size(), System.currentTimeMillis() - start, delta));
        for (List<Integer> indexes : layers) {
            color = color + delta;
            for (int i : indexes) data[i] = color;
        }
        byte[] dstData = new byte[total];
        for (int i = 0; i < total; i++) dstData[i] = (byte) (data[i] & 0xff);
        Mat dst = new Mat(gray.size(), gray.type());
        dst.put(0, 0, dstData);
        imshow("结果", dst);
    }

    private void bfs(int rows, int cols, int[] data, List<List<Integer>> layers, Pixel first) {
        int index;
        int newColor;
        List<Integer> indexes = new ArrayList<>();
        LinkedList<Pixel> bfs = new LinkedList<>();
        bfs.push(first);
        while (!bfs.isEmpty()) {
            Pixel pop = bfs.pop();
            if (pop.getRow() < 0 || pop.getRow() >= rows) continue;
            if (pop.getCol() < 0 || pop.getCol() >= cols) continue;
            index = pop.getRow() * cols + pop.getCol();
            newColor = data[index];
            if (newColor == -1) continue;
            if (Math.abs(newColor - first.getCompareColor()) <= 5) {
                indexes.add(index);
                data[index] = -1;
                bfs.push(new Pixel().setRow(pop.getRow()).setCol(pop.getCol() - 1).setCompareColor(newColor));
                bfs.push(new Pixel().setRow(pop.getRow()).setCol(pop.getCol() + 1).setCompareColor(newColor));
                bfs.push(new Pixel().setRow(pop.getRow() - 1).setCol(pop.getCol() - 1).setCompareColor(newColor));
                bfs.push(new Pixel().setRow(pop.getRow() - 1).setCol(pop.getCol()).setCompareColor(newColor));
                bfs.push(new Pixel().setRow(pop.getRow() - 1).setCol(pop.getCol() + 1).setCompareColor(newColor));
                bfs.push(new Pixel().setRow(pop.getRow() + 1).setCol(pop.getCol() - 1).setCompareColor(newColor));
                bfs.push(new Pixel().setRow(pop.getRow() + 1).setCol(pop.getCol()).setCompareColor(newColor));
                bfs.push(new Pixel().setRow(pop.getRow() + 1).setCol(pop.getCol() + 1).setCompareColor(newColor));
            }
        }
        if (indexes.size() > 25) {
            layers.add(indexes);
        }
    }
}
